package com.ytjj.qmyx.mall.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayConfig;
import com.github.wxpay.sdk.WXPayConstants;
import com.github.wxpay.sdk.WXPayUtil;
import com.ytjj.common.constants.CopyWriterConstant;
import com.ytjj.common.exception.ApiException;
import com.ytjj.common.utils.CopyWriterConfigUtil;
import com.ytjj.qmyx.mall.config.MyWxConfig;
import com.ytjj.qmyx.mall.constants.CompanyConstant;
import com.ytjj.qmyx.mall.mapper.OrdersDao;
import com.ytjj.qmyx.mall.mapper.OrdersPayMapper;
import com.ytjj.qmyx.mall.mapper.PayConfigMapper;
import com.ytjj.qmyx.mall.mapper.SysConfigMapper;
import com.ytjj.qmyx.mall.model.OrdersPay;
import com.ytjj.qmyx.mall.model.OrdersPayExample;
import com.ytjj.qmyx.mall.model.PayConfig;
import com.ytjj.qmyx.mall.model.dto.WxAppPayDto;
import com.ytjj.qmyx.mall.model.response.WxAppPayResponse;
import com.ytjj.qmyx.mall.service.WxService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 微信app 发起预付款
 *
 *
 * @version 1.0
 * 
 */
@Service("APP-APP")
@Slf4j
public class WxAppServiceImpl implements WxService<WxAppPayDto> {

    @Resource
    private OrdersDao ordersDao;
    @Resource
    private CopyWriterConfigUtil copyWriterConfigUtil;
    @Resource
    private OrdersPayMapper ordersPayMapper;
    @Resource
    private PayConfigMapper payConfigMapper;

    public static final String TYPE = "APP";

    public static final String TRADE_TYPE = "APP";
    public static final String APP_PHONE_CHARGE = "APP_PHONE_CHARGE";

    @Override
    public Map<String, String> doUnifiedOrder(WxAppPayDto wxAppPayDto) throws Exception {
        PayConfig payConfig = ordersDao.getPayConfigByCompany(CompanyConstant.PLATFORM, TYPE, TRADE_TYPE);
        MyWxConfig myWxConfig = new MyWxConfig(payConfig);

        Map<String, String> data = new HashMap<>();
        data.put("appid", payConfig.getAppid());
        data.put("notify_url", payConfig.getNotifyUrl());
        data.put("attach", "");
        WXPay wxpay = new WXPay(myWxConfig, WXPayConstants.SignType.MD5);
        data.put("mch_id", payConfig.getMchId());
        data.put("nonce_str", WXPayUtil.generateNonceStr());
        data.put("body", wxAppPayDto.getBody());
        data.put("out_trade_no", wxAppPayDto.getResOrderNo());
        data.put("total_fee", wxAppPayDto.getRealTotalMoney());
        data.put("spbill_create_ip", payConfig.getSpbillCreateIp());
        data.put("trade_type", TRADE_TYPE);
        data.put("sign", WXPayUtil.generateSignature(data, payConfig.getWxKey(),
                WXPayConstants.SignType.MD5));

        Map<String, String> response = wxpay.unifiedOrder(data);
        log.info("===doUnifiedOrder.response==={}", response);
        if ("SUCCESS".equals(response.get("return_code"))) {
            Map<String, String> param = new HashMap<>();
            param.put("appid", payConfig.getAppid());
            param.put("partnerid", response.get("mch_id"));
            param.put("prepayid", response.get("prepay_id"));
            param.put("package", "Sign=WXPay");
            param.put("noncestr", WXPayUtil.generateNonceStr());
            param.put("timestamp", System.currentTimeMillis() / 1000 + "");
            param.put("sign", WXPayUtil.generateSignature(param, payConfig.getWxKey(),
                    WXPayConstants.SignType.MD5));
            param.put("payConfigId", String.valueOf(payConfig.getId()));
            return param;
        }
        throw new ApiException(copyWriterConfigUtil.getCopyWriterValue(CopyWriterConstant.ORDER_FAILED));
    }

    /**
     * 话费充值退款
     * @param wxAppPayDto
     * @return
     * @throws Exception
     */
    @Override
    public Map<String, String> doUnifiedRechargeOrder(WxAppPayDto wxAppPayDto) throws Exception {
        PayConfig payConfig = ordersDao.getPayConfigByCompany(CompanyConstant.PLATFORM, TYPE, APP_PHONE_CHARGE);
        MyWxConfig myWxConfig = new MyWxConfig(payConfig);

        Map<String, String> data = new HashMap<>();
        data.put("appid", payConfig.getAppid());
        data.put("notify_url", payConfig.getNotifyUrl());
        data.put("attach", "");
        WXPay wxpay = new WXPay(myWxConfig, WXPayConstants.SignType.MD5);
        data.put("mch_id", payConfig.getMchId());
        data.put("nonce_str", WXPayUtil.generateNonceStr());
        data.put("body", wxAppPayDto.getBody());
        data.put("out_trade_no", wxAppPayDto.getResOrderNo());
        data.put("total_fee", wxAppPayDto.getRealTotalMoney());
        data.put("spbill_create_ip", payConfig.getSpbillCreateIp());
        data.put("trade_type", TRADE_TYPE);
        data.put("sign", WXPayUtil.generateSignature(data, payConfig.getWxKey(),
                WXPayConstants.SignType.MD5));

        Map<String, String> response = wxpay.unifiedOrder(data);
        if ("SUCCESS".equals(response.get("return_code"))) {
            Map<String, String> param = new HashMap<>();
            param.put("appid", payConfig.getAppid());
            param.put("partnerid", response.get("mch_id"));
            param.put("prepayid", response.get("prepay_id"));
            param.put("package", "Sign=WXPay");
            param.put("noncestr", WXPayUtil.generateNonceStr());
            param.put("timestamp", System.currentTimeMillis() / 1000 + "");
            param.put("sign", WXPayUtil.generateSignature(param, payConfig.getWxKey(),
                    WXPayConstants.SignType.MD5));
            return param;
        }
        throw new ApiException(copyWriterConfigUtil.getCopyWriterValue(CopyWriterConstant.ORDER_FAILED));
    }

    @Override
    public Map<String, String> wxOrderQuery(String resOrderNo) throws Exception {
        PayConfig payConfig = ordersDao.getPayConfigByCompany(CompanyConstant.PLATFORM, TYPE, TRADE_TYPE);
        MyWxConfig myWxConfig = new MyWxConfig(payConfig);

        Map<String, String> data = new HashMap<>();
        data.put("appid", payConfig.getAppid());
        WXPay wxpay = new WXPay(myWxConfig, WXPayConstants.SignType.MD5);

        data.put("mch_id", payConfig.getMchId());
        data.put("out_trade_no", resOrderNo);
        data.put("nonce_str", WXPayUtil.generateNonceStr());
        data.put("sign", WXPayUtil.generateSignature(data, payConfig.getWxKey(),
                WXPayConstants.SignType.MD5));
        log.info("微信app支付状态查询请求 订单号：{},query: {}", resOrderNo, JSONObject.toJSONString(data));
        //使用官方API请求预付订单
        Map<String, String> response = wxpay.orderQuery(data);
        log.info("微信app支付状态查询响应 订单号：{},response: {}", resOrderNo, JSONObject.toJSONString(response));
        return response;
    }

    @Override
    public Map<String, String> wxPhoneChargesQuery(String resOrderNo) {
        return null;
    }

    @Override
    public Map refundOrders(String outTradeNo, String outRefundNo, Integer totalFee, Integer refundFee, String refundDesc) throws Exception {
//        PayConfig payConfig = ordersDao.getPayConfigByCompany(CompanyConstant.PLATFORM, TYPE, TRADE_TYPE);
        OrdersPayExample ordersPayExample = new OrdersPayExample();
        ordersPayExample.createCriteria().andResOrderNoEqualTo(outTradeNo).andPayTypeEqualTo(new Byte("2"));
        ordersPayExample.setOrderByClause("id desc");
        List<OrdersPay> ordersPays = ordersPayMapper.selectByExample(ordersPayExample);
        PayConfig payConfig = null;
        if (!CollectionUtils.isEmpty(ordersPays)) {
            if (null != ordersPays.get(0).getPayConfigId()) {
                payConfig = payConfigMapper.selectByPrimaryKey(ordersPays.get(0).getPayConfigId());
            }
        }
        if (null == payConfig) {
            throw new ApiException("退款失败，请联系管理员！！！");
        }
        MyWxConfig myWxConfig = new MyWxConfig(payConfig);

        Map<String, String> data = new HashMap<>();
        //生成商户订单号，不可重复
        WXPay wxpay = new WXPay(myWxConfig, WXPayConstants.SignType.MD5);
        data.put("appid", payConfig.getAppid());
        data.put("mch_id", payConfig.getMchId());
        data.put("nonce_str", WXPayUtil.generateNonceStr());
        data.put("out_trade_no", outTradeNo);
        data.put("out_refund_no", outRefundNo);
        data.put("total_fee", String.valueOf(totalFee));
        data.put("refund_fee", String.valueOf(refundFee));
//        data.put("refund_desc", refundDesc);
        data.put("notify_url", payConfig.getRefundNotifyUrl());
        data.put("sign", WXPayUtil.generateSignature(data, payConfig.getWxKey(),
                WXPayConstants.SignType.MD5));
        Map<String, String> response = wxpay.refund(data);
        log.info("微信发起退款：response:{}",JSONObject.toJSONString(response));
        return response;
    }

    @Override
    public Map refundRecharge(String outTradeNo, String outRefundNo, Integer totalFee, Integer refundFee, String refundDesc) throws Exception {
        PayConfig payConfig = ordersDao.getPayConfigByCompany(CompanyConstant.PLATFORM, TYPE, APP_PHONE_CHARGE);
        MyWxConfig myWxConfig = new MyWxConfig(payConfig);

        Map<String, String> data = new HashMap<>();
        //生成商户订单号，不可重复
        WXPay wxpay = new WXPay(myWxConfig, WXPayConstants.SignType.MD5);
        data.put("appid", payConfig.getAppid());
        data.put("mch_id", payConfig.getMchId());
        data.put("nonce_str", WXPayUtil.generateNonceStr());
        data.put("out_trade_no", outTradeNo);
        data.put("out_refund_no", outRefundNo);
        data.put("total_fee", String.valueOf(totalFee));
        data.put("refund_fee", String.valueOf(refundFee));
//        data.put("refund_desc", refundDesc);
        data.put("notify_url", payConfig.getRefundNotifyUrl());
        data.put("sign", WXPayUtil.generateSignature(data, payConfig.getWxKey(),
                WXPayConstants.SignType.MD5));
        Map<String, String> response = wxpay.refund(data);
        log.info("微信发起退款：response:{}",JSONObject.toJSONString(response));
        return response;
    }


}
